home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / PTMID3.ZIP / PTMIDZAP.C < prev    next >
C/C++ Source or Header  |  1994-07-02  |  7KB  |  216 lines

  1. /*
  2.  * ptmidzap.c: Resolution module for ptmid. Takes a structure representing
  3.  * a tune and tries to make it fit into 4 channels.
  4.  *
  5.  * Author: Andrew Scott  (c)opyright 1994
  6.  *
  7.  * Date: 17/11/1993 ver 0.0
  8.  *       8/1/1994   ver 0.1
  9.  *       11/2/1994  ver 0.2
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include "ptmid.h"
  15.  
  16. MS rgmsDecided[MAXSAMPS];
  17. int cmsDecided, wMinpitch, wMaxpitch;
  18.  
  19. /**
  20.  ** The midivolume array holds Protracker equivants of MIDI velocities.
  21.  ** It allows fast velocity-volume conversion.
  22.  **/
  23. unsigned midivolume[128] = {
  24.      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
  25.     16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
  26.     32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
  27.     48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
  28.     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
  29.     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
  30.     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
  31.     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
  32.   };
  33.  
  34. /*
  35.  * Init: Initializes stuff that should be initialized.
  36.  *
  37.  * date: 1/7/1994 - added init of min/max pitches & default period array
  38.  */
  39. static void Init(void)
  40. {
  41.   int ims = MAXSAMPS;
  42.  
  43.     while (ims--) { /** Put default values in sample array **/
  44.         sprintf(rgmsDecided[ims].szName, "%02d: --", ims);
  45.     rgmsDecided[ims].psi = NULL;
  46.         rgmsDecided[ims].bDefvol = 0;
  47.     }
  48.   cmsDecided = 0;
  49.   if (fExtend) {
  50.     wMinpitch = MIDDLEC - 24;
  51.     wMaxpitch = MIDDLEC + 36;
  52.   } else {
  53.     wMinpitch = MIDDLEC - 12;
  54.     wMaxpitch = MIDDLEC + 24;
  55.   }
  56. }
  57.  
  58. /*
  59.  * FitSzBFn: Given a filename, will fit it into the given sample name,
  60.  * and prepend given number, ensuring that it doesn't overflow the
  61.  * 22 character array.
  62.  */
  63. void FitSzBFn(Sz szName, int bPos, Sz fnSample)
  64. {
  65.     int iT = 18;
  66.  
  67.     sprintf(szName, "%02d: ", bPos); /** First the number **/
  68.     szName += 4;
  69.     while (iT-- && (*(szName++) = *(fnSample++))); /** Then the name **/
  70. }
  71.  
  72. /*
  73.  * WConvertMidipitch: Given a MIDI pitch, returns a pitch in the range
  74.  * allowed for output. If none can be found (only for wRgmode = 0), -2 is
  75.  * returned. If the pitch is out of range, then the value of the given
  76.  * pointer is incremented.
  77.  *
  78.  * date: 1/7/1994
  79.  */
  80. int WConvertMidipitch(int pitch, unsigned long *cDev)
  81. {
  82.   switch (wRgmode) {
  83.     case 0:
  84.       if (pitch < wMinpitch) {
  85.         if (fStats)
  86.           (*cDev)++;
  87.         pitch = wMinpitch;
  88.       } else if (pitch >= wMaxpitch) {
  89.         if (fStats)
  90.           (*cDev)++;
  91.         pitch = wMaxpitch - 1;
  92.       }
  93.       break;
  94.     case 1:
  95.       if (pitch < wMinpitch || pitch >= wMaxpitch) {
  96.         if (fStats)
  97.           (*cDev)++;
  98.         pitch = -2;
  99.       }
  100.       break;
  101.     case 2:
  102.       if (pitch < wMinpitch) {
  103.         if (fStats)
  104.           (*cDev)++;
  105.         pitch += ((wMinpitch - pitch + 11) / 12) * 12;
  106.       } else if (pitch >= wMaxpitch) {
  107.         if (fStats)
  108.           (*cDev)++;
  109.         pitch -= ((pitch - wMaxpitch + 12) / 12) * 12;
  110.       }
  111.   }
  112.   return pitch;
  113. }
  114.  
  115. /*
  116.  * AnalyzePtune: Given a tune, searches through and allocates samples
  117.  * to sample array rgmsDecided (includes determining mixes).
  118.  * Eventually (?) this will become much more extensive, and include
  119.  * compacting by changing tempo, filtering of quiet notes, and identification
  120.  * of common chords and replacing these with a separate sample.
  121.  *
  122.  * date: 1/7/1994 - added calls to WConvertMidipitch
  123.  */
  124. void AnalyzePtune(Tune *ptune)
  125. {
  126.     unsigned long Lastnoise = 0, cDev = 0;
  127.     EI *pei;
  128.     SI *psi, **ppsi;
  129.  
  130.     while (NULL != ptune) { /** While not at end of tune **/
  131.     for (pei = ptune->pei; NULL != pei; pei = pei->pei) { /** With each event **/
  132.       if (-1 != pei->pitch) {
  133.                 if (ptune->count + pei->effect > Lastnoise) /** Find the note which **/
  134.                     Lastnoise = ptune->count + pei->effect; /** will carry the longest **/
  135.  
  136.         if (pei->inst < 0) /** If a percussion instrument **/
  137.           if ((psi = rgpsiDrum[-1 - pei->inst]) == NULL)
  138.             pei->pitch = -2;
  139.           else
  140.             pei->pitch = WConvertMidipitch(MIDDLEC + psi->perpitch -
  141.               psi->pitch, &cDev);
  142.         else { /** Else if a non-percussion instrument **/
  143.           unsigned wMin;
  144.  
  145.           if ((ppsi = rgppsiIns[pei->inst]) == NULL)
  146.             ppsi = rgppsiIns[128];
  147.           psi = *(ppsi++);
  148.           wMin = abs(psi->pitch - pei->pitch);
  149.           for (; NULL != *ppsi; ppsi++) /** Find closest matching sample **/
  150.             if (abs((*ppsi)->pitch - pei->pitch) < wMin) {
  151.               psi = *ppsi;
  152.               wMin = abs(psi->pitch - pei->pitch);
  153.             }
  154.           pei->pitch = WConvertMidipitch(MIDDLEC + pei->pitch - psi->pitch,
  155.             &cDev);
  156.         }
  157.         pei->vol = midivolume[pei->vol]; /** Convert volumes **/
  158.  
  159.         if (NULL != psi) /** If sample info **/
  160.           if (-1 != psi->sample) /** and sample has been used before **/
  161.             pei->inst = psi->sample; /** use that sample for instrument **/
  162.           else if (MAXSAMPS == cmsDecided) /** Else if no samples left **/
  163.             pei->pitch = -2; /** make note invalid **/
  164.  
  165.           else { /** Else we've got a new sample **/
  166.             FitSzBFn(rgmsDecided[cmsDecided].szName, cmsDecided,
  167.               psi->fnSample); /** Fix up it's name **/
  168.             rgmsDecided[cmsDecided].bDefvol = 64;
  169.             rgmsDecided[cmsDecided].psi = psi;
  170.             psi->sample = pei->inst = cmsDecided++;
  171.           }
  172.       }
  173.     }
  174.         ptune = ptune->ptune;
  175.     }
  176.     if (fStats)
  177.         printf(" Number of pitch conversions out of range: %lu\n", cDev);
  178. }
  179.  
  180. /*
  181.  * UnitifyPtune: Given a tune, will convert lengths into division multiples.
  182.  */
  183. void UnitifyPtune(Tune *ptune)
  184. {
  185.     EI *pei;
  186.  
  187.     while (NULL != ptune) { /** While not end of tune **/
  188.         pei = ptune->pei;
  189.         ptune->count /= wQuant; /** Divide intervals by quantize amount **/
  190.         ptune = ptune->ptune;
  191.         while (NULL != pei) { /** Go through each event **/
  192.       if (-1 != pei->pitch)
  193.                 pei->effect /= wQuant; /** Divide durations by quantize amount **/
  194.       pei = pei->pei;
  195.         }
  196.     }
  197. }
  198.  
  199. /*
  200.  * ResolvePtune: Given a tune, goes through and finds out useful stuff
  201.  * about it for use in creating a MOD-file. Also trims off chords that
  202.  * are too big, notes that are too quiet, etc.
  203.  */
  204. void ResolvePtune(Tune *ptune)
  205. {
  206.     Init();
  207. #if 0
  208.     FilterPtune(ptune);
  209.     Calcchords();
  210.     ConvertPtune(ptune);
  211.     Storevols();
  212. #endif
  213.     AnalyzePtune(ptune);
  214.     UnitifyPtune(ptune);
  215. }
  216.